package cc.rengu.igas.cops.core.realize.impl;
/*
 *Create by fuyp on 2020-9-15
 */

import cc.rengu.igas.acct.facade.bean.MchtAdjustDetail;
import cc.rengu.igas.acct.facade.request.VirtAcctMultiMchntAdjustRequest;
import cc.rengu.igas.channel.ncqs.facade.bean.RiskInfo;
import cc.rengu.igas.cops.common.constant.CopsParamConstant;
import cc.rengu.igas.cops.common.enums.RespCodeEnum;
import cc.rengu.igas.cops.core.realize.PublicDealService;
import cc.rengu.igas.momp.facade.bean.ClaimCouponMcInfoBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderDetailBean;
import cc.rengu.igas.momp.facade.request.ClaimCouponRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentReversalRequest;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.constant.ShareTreeNodeConstant;
import cc.rengu.igas.share.common.enums.FeeTypeEnum;
import cc.rengu.igas.share.common.enums.SettleAcctTypeEnum;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.core.model.MchntAcctInfo;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.TransLimitBean;
import cc.rengu.igas.share.core.realize.CsmcService;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.CsmcServiceImpl;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.smps.facade.base.Header;
import cc.rengu.igas.smps.facade.request.AlarmNoticeRequest;
import cc.rengu.igas.smps.facade.request.BankFourElementVerifyRequest;
import cc.rengu.igas.smps.facade.response.BankFourElementVerifyResponse;
import cc.rengu.igas.smps.facade.result.Result;
import cc.rengu.jradp.asynnotify.AsynNotify;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.UserOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.UserOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.TransLimitInfo;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.*;
import cc.rengu.oltp.service.realize.impl.*;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.TimeUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class PublicDealServiceImpl implements PublicDealService {
    private final RgLogger rglog = RgLog.getLogger(this.getClass().getName());
    private boolean isCouponTrans = false;

    @Override
    public void bankFourEleVerify(String instId, String acctNo, String certNo, String certType, String mobilePhone, String custName) throws Exception {
        rglog.debug("本行借记卡四要素认证开始");
        Header esbHeader = new Header();
        esbHeader.setChanlId(ChannelEnum.COPS.getChannelType());
        esbHeader.setSrcSysId(AppParamConstant.SYS_ID);
        esbHeader.setBizType("00");
        esbHeader.setTxnNum("00010000523800");
        esbHeader.setVersion("1.0.0");
        esbHeader.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(instId));
        esbHeader.setTransTime(DateUtil.getCurrentTime());
        esbHeader.setTransDate(DateUtil.getCurrentDate());
        esbHeader.setInstId(instId);
        BankFourElementVerifyRequest request = new BankFourElementVerifyRequest();
        request.setHeader(esbHeader);
        request.setCustomerName(custName);
        request.setAcctNo(acctNo);
        request.setCertNo(certNo);
        request.setCertType(certType);
        request.setMobileNo(mobilePhone);
        rglog.debug("四要素认证请求报文<{}>", JSON.toJSONString(request));
        DubboService dubboService = new DubboServiceImpl();
        Result<BankFourElementVerifyResponse> esbResult = (Result<BankFourElementVerifyResponse>) dubboService.callDubboService(CopsParamConstant.DUBBO_BANK_SUP_SERVICE, "bankFourElementVerify", request);
        if (null == esbResult || !esbResult.isSuccess()) {
            rglog.warn("调用dubbo服务bankSupService->bankFourElementVerify失败");
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (!CopsParamConstant.DUBBO_SUCCESS.equals(esbResult.getResult().getRespCode())) {
            rglog.warn("调用dubbo服务bankSupService->bankFourElementVerify失败.respCode<{}>,respDesc<{}>", esbResult.getResult().getRespCode(), esbResult.getResult().getRespDesc());
            throw new BizException(esbResult.getResult().getRespCode(), esbResult.getResult().getRespDesc());
        }
        rglog.debug("本行借记卡四要素认证结束");
    }

    @Override
    public void checkSmsSignNotify(String instId, String acctNo, String certNo, String certType, String mobilePhone) throws Exception {
        rglog.debug("签约短息通知开通校验开始");
        //TODO 核心短信通知签约查询
    }

    @Override
    public void debitCardCoreSign(String instId, String acctNo, String certNo, String certType, String signInst, String custName) throws Exception {
        rglog.debug("调用本行签约开始....");
        //TODO 调用本行签约
    }

    @Override
    public void checkUserOrderPayValidity(UserOrderInfo userOrderInfo, String orderAmt) throws Exception {
        if (OrderStatusEnum.CLOSE.getStatus().equals(userOrderInfo.getOrderStatus())) {
            rglog.info("用户订单已关闭.orderStatus:<{}>", userOrderInfo.getOrderStatus());
            throw new BizException(RespCodeEnum.ORDER_CLOSED.getRespCode(), RespCodeEnum.ORDER_CLOSED.getRespDesc());
        } else if (OrderStatusEnum.INVALID.getStatus().equals(userOrderInfo.getOrderStatus())) {
            rglog.info("用户订单已过期.orderStatus:<{}>", userOrderInfo.getOrderStatus());
            throw new BizException(RespCodeEnum.ORDER_EXPR_ERROR.getRespCode(), RespCodeEnum.ORDER_EXPR_ERROR.getRespDesc());
        } else if (OrderStatusEnum.FINISH.getStatus().equals(userOrderInfo.getOrderStatus())) {
            rglog.info("用户订单已完成.orderStatus:<{}>", userOrderInfo.getOrderStatus());
            throw new BizException(RespCodeEnum.ORDER_FINISH.getRespCode(), RespCodeEnum.ORDER_FINISH.getRespDesc());
        } else if (BizStatusEnum.PROCESSING.getStatus().equals(userOrderInfo.getBizStatus())) {
            rglog.info("用户订单处理处理中，不允许再次发起支付。bizStatus:<{}>", userOrderInfo.getBizStatus());
            throw new BizException(RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespCode(), RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespDesc());
        }
        /*比较金额，金额不一致，是用户订单表订单金额：0、null两种情况*/
        if (AmountUtil.compare(orderAmt, userOrderInfo.getOrderAmt()) != 0 &&
                (AmountUtil.compare("0", userOrderInfo.getOrderAmt()) != 0 || !StringUtil.isEmptyOrNull(userOrderInfo.getOrderAmt()))) {
            rglog.info("订单金额不一致，transAmt:<{}>,orderAmt:<{}>", orderAmt, userOrderInfo.getOrderAmt());
            throw new BizException(RespCodeEnum.TRANS_AMT_DISACCORD.getRespCode(), RespCodeEnum.TRANS_AMT_DISACCORD.getRespDesc());
        }
        /*判断订单是否超过有效期*/
        if (DateUtil.compareTime(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"),
                userOrderInfo.getOrderExpiryTime(), "yyyyMMddHHmmss") > 0) {
            rglog.info("订单已经过了有效期，当前日期curDateTime:<{}>,订单有效期orderExpiryTime:<{}>",
                    DateUtil.getCurrentDateTime("yyyyMMddHHmmss"), userOrderInfo.getOrderExpiryTime());
            /*订单已失效更新订单已失效*/
            OrderService orderService = new OrderServiceImpl();
            userOrderInfo.setOrderStatus(OrderStatusEnum.INVALID.getStatus());
            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, null, null)) {
                rglog.error("更新用户订单/商户订单信息失败");
            }
            throw new BizException(RespCodeEnum.ORDER_EXPR_ERROR.getRespCode(), RespCodeEnum.ORDER_EXPR_ERROR.getRespDesc());
        }
    }

    @Override
    public String getOrderExpiryTime(String instId, String orderExprityTime, String orderCreateTime) throws Exception {
        /*获取订单有效时间*/
        String exprityTime;
        if (StringUtil.isEmptyOrNull(orderExprityTime)) {
            SysParamService sysParamService = new SysParamServiceImpl();
            SysParam sysParamInfo = sysParamService.getSysParamInfo(instId, CopsParamConstant.OPMS_SYS_PARAM,
                    CopsParamConstant.ORDER_EXPIRY_TIME);
            exprityTime = sysParamInfo == null || StringUtil.isEmptyOrNull(sysParamInfo.getParamValue()) ?
                    CopsParamConstant.ORDER_DEFAULT_EXPIRY_TIME : sysParamInfo.getParamValue();
        } else {
            exprityTime = orderExprityTime;
        }
        return TimeUtil.calcDays(orderCreateTime, Long.valueOf(exprityTime));
    }

    @Override
    public boolean judgeMchntD0Flag(List<MchntOrderInfo> mchntOrderInfoList) throws Exception {
        /*查询D0入账金额参数*/
        OrderService orderService = new OrderServiceImpl();
        String d0MinAmt = "0.00";
        String instId = mchntOrderInfoList.get(0).getInstId();
        boolean d0Flag = true;
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(instId, ShareParamConstant.MCHNT_SERVICE,
                ShareParamConstant.D0_ACCOUNTING_MIN_AMT);
        if (sysParam == null) {
            rglog.warn("未配置商户d0入账最低金额，使用默认最低金额");
            d0MinAmt = ShareParamConstant.DEFAULT_D0_ACCOUNTING_MIN_AMT;
        } else {
            d0MinAmt = sysParam.getParamValue();
        }
        rglog.debug("商户实时入账最低金额<{}>", d0MinAmt);
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            /*如果所有商户订单金额都大于最小D0实时入账金额才能D0入账*/
            d0Flag = d0Flag && AmountUtil.compare(mchntOrderInfo.getRealSettleAmt(), d0MinAmt) > 0;
        }
        if (!d0Flag) {
            rglog.debug("存在商户入账金额小于D0最小入账金额:<{}>", d0MinAmt);
            /*更新商户入账D0标识为N*/
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                mchntOrderInfo.setRealSettleFlag("N");
                mchntOrderInfo.setRealSettleType("");
            }
            orderService.updateOrderInfo(null, mchntOrderInfoList, null);
        }
        return d0Flag;
    }

    @Override
    public void mchntRealTimeAccouting(List<MchntOrderInfo> mchntOrderInfoList) throws Exception {
        /*处理微信、支付宝、银联D0入账服务*/
        rglog.debug("商户DO入账开始....");
        DubboService dubboService = new DubboServiceImpl();
        String instId = mchntOrderInfoList.get(0).getInstId();
        int callIndex = 0;
        /*获取垫支户*/
        CsmcService csmcService = new CsmcServiceImpl();
        String roleActualAcctNo = csmcService.getRoleActualAcctNo(instId, SettleAcctTypeEnum.DZ_SUBJECT.getSettleAcct(), null);
        if (StringUtil.isEmptyOrNull(roleActualAcctNo)) {
            rglog.error("获取垫资户信息失败，商户实时入账失败，转t1");
            return;
        }
        /*查询商户结算账户信息表，判断结算周期及结算账户类型*/
        List<MchntAcctInfo> mchntAcctInfoList;

        /*合并订单循环每个商户处理D0*/
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo;
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
            /*判断是否独立维护资料的门店*/
            if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                mchntAcctInfoList = mchntService.getMchntAcctInfo(instId, mchntInfo.getChainMchntNo());
            } else {
                mchntAcctInfoList = mchntService.getMchntAcctInfo(instId, mchntOrderInfo.getMchntNo());
            }
            Optional<MchntAcctInfo> mchntAcctInfoOpt = mchntAcctInfoList.stream().filter(item -> item.getBaseProdCode().equals(mchntOrderInfo.getBizProdCode()) && item.getFundType().equals("00")).findFirst();
            if (!mchntAcctInfoOpt.isPresent()) {
                rglog.warn("获取商户结算账户信息失败，商户<{}>实时入账失败，转t1", mchntOrderInfo.getMchntNo());
                continue;
            }
            /*登记D0订单信记录*/
            PayOrderInfo payOrderInfo = registerD0PayOrderInfo(mchntInfo, mchntOrderInfo,
                    roleActualAcctNo, AcctTypeEnum.BANK_ACCT.getAcctType(),
                    mchntAcctInfoOpt.get().getSettleAcctNo(), mchntAcctInfoOpt.get().getSettleAcctType(), String.valueOf(callIndex));
            if (payOrderInfo == null) {
                rglog.warn("商户:<{}>D0支付订单登记失败", mchntOrderInfo.getMchntNo());
                continue;
            } else {
                rglog.debug("D0支付订单表<{}>", JSON.toJSONString(payOrderInfo));
            }
            //TODO 由项目组实现该部分 调用D0实时清算，后调用AsynMchntD0AccoutingService根据清算结果进行处理
            int iReturnCode = dubboService.asynCallDubboService("dubboService", "method", "request", "AsynMchntD0AccoutingService");
            if (iReturnCode != 0) {
                rglog.debug("商户<{}>异步d0入账服务注册失败！", mchntOrderInfo.getMchntNo());
            }
            callIndex++;
        }
    }

    /*登记D0记账支付订单流水*/
    private PayOrderInfo registerD0PayOrderInfo(MchntInfo mchntInfo, MchntOrderInfo mchntOrderInfo,
                                                String payAcctNo, String payAcctType, String payeeAcctNo,
                                                String payeeAcctType, String callIndex) throws Exception {
        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(mchntOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(CopsParamConstant.D0_ACCOUTING_TXN_NUM);
        /*系统流水号取下单交易的系统流水号*/
        payOrderInfo.setSysSeqNum(mchntOrderInfo.getSysSeqNum());
        payOrderInfo.setMsgDstId(ChannelEnum.ESB.getChannelType());
        if (callIndex != null) {
            payOrderInfo.setDstCallIndex(callIndex);
            /*对账唯一key,与批量平台*/
            payOrderInfo.setChannelSeqNum(mchntOrderInfo.getSysSeqNum() + callIndex);
            /*对账唯一key，与核心平台*/
            payOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntOrderInfo.getInstId()));
        } else {
            payOrderInfo.setDstCallIndex("0");
            payOrderInfo.setChannelSeqNum(mchntOrderInfo.getSysSeqNum() + "0");
            payOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntOrderInfo.getInstId()));
        }
        payOrderInfo.setChannelBizType(ShareParamConstant.OTHER_SUB_SYS_ID_D0_REALTIME);
        /*收支两条线*/
        if ('1' == mchntInfo.getMchntSettleMode().charAt(1)) {
            payOrderInfo.setRealPayAmt(mchntOrderInfo.getRealSettleAmt());
        } else {
            payOrderInfo.setRealPayAmt(mchntOrderInfo.getMchntSettleAmt());
        }
        payOrderInfo.setDstTxnNum("00010000175500");
        payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
        payOrderInfo.setPayerAcctType(payAcctType);
        payOrderInfo.setPayerAcctInfo(payAcctNo);
        payOrderInfo.setPayeeAcctType(payeeAcctType);
        payOrderInfo.setPayeeAcctInfo(payeeAcctNo);
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        }
        return payOrderInfo;
    }

    @Override
    public void virtAcctMultiMchntAdjust(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, AsynNotify asynnotify) throws Exception {
        /*定义应用变量*/
        OrderService orderService = new OrderServiceImpl();
        DubboService dubboService = new DubboServiceImpl();
        /*初始化参数*/
        /*交易机构*/
        String instId = userOrderInfo.getInstId();
        /*原支付交易系统流水号*/
        String sysSeqNum = mchntOrderInfoList.get(0).getSysSeqNum();
        /*原支付交易交易码*/
        String txnNum = mchntOrderInfoList.get(0).getTxnNum();
        /*原支付交易业务细分*/
        String bizType = mchntOrderInfoList.get(0).getBizType();
        /*目标通道交易码*/
        String dstTxnNum = "P01AT002";
        /*初始化虚拟账记账订单*/
        PayOrderInfo virtAcctMultiMchntAdjustOrderInfo = new PayOrderInfo();
        virtAcctMultiMchntAdjustOrderInfo.setInstId(instId);
        virtAcctMultiMchntAdjustOrderInfo.setTxnDate(DateUtil.getCurrentDate());
        virtAcctMultiMchntAdjustOrderInfo.setTxnTime(DateUtil.getCurrentTime());
        /*虚拟账户单笔记账的交易码*/
        virtAcctMultiMchntAdjustOrderInfo.setTxnNum(txnNum);
        virtAcctMultiMchntAdjustOrderInfo.setBizType(bizType);
        /*通道交易码*/
        virtAcctMultiMchntAdjustOrderInfo.setDstTxnNum(dstTxnNum);
        /*系统流水号*/
        virtAcctMultiMchntAdjustOrderInfo.setSysSeqNum(sysSeqNum);
        /*单笔记账对账唯一主键,可以通过对账主键控制并发*/
        virtAcctMultiMchntAdjustOrderInfo.setChannelReconKey(sysSeqNum + "0");
        /*通道流水号*/
        virtAcctMultiMchntAdjustOrderInfo.setChannelSeqNum(sysSeqNum + "0");
        /*处理多笔商户订单交易*/
        if (mchntOrderInfoList.size() > 1) {
            /*多笔订单默认保存平台商户号*/
            virtAcctMultiMchntAdjustOrderInfo.setMchntNo(userOrderInfo.getGroupMchntNo());
        } else {
            /*单笔订单记录商户号*/
            virtAcctMultiMchntAdjustOrderInfo.setMchntNo(mchntOrderInfoList.get(0).getMchntNo());
        }
        /*商户订单号*/
        virtAcctMultiMchntAdjustOrderInfo.setMchntOrderId(userOrderInfo.getMchntOrderId());
        /*商户单笔记账金额*/
        virtAcctMultiMchntAdjustOrderInfo.setOrderAmt(userOrderInfo.getOrderAmt());
        virtAcctMultiMchntAdjustOrderInfo.setOrderCcy("156");
        /*设置通道标识和通道序号*/
        virtAcctMultiMchntAdjustOrderInfo.setMsgDstId(ChannelEnum.ACCT.getChannelType());
        /*设置支付类型*/
        virtAcctMultiMchntAdjustOrderInfo.setPayType("*");
        /*设置付款账户类型*/
        virtAcctMultiMchntAdjustOrderInfo.setPayerAcctType("*");
        /*设置通到序号*/
        virtAcctMultiMchntAdjustOrderInfo.setDstCallIndex("0");
        /*设置订单创建时间*/
        virtAcctMultiMchntAdjustOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        virtAcctMultiMchntAdjustOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        /*设置订单状态*/
        virtAcctMultiMchntAdjustOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        virtAcctMultiMchntAdjustOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        /*在异步程序中处理对应的订单状态*/
        /*组装请求报文头*/
        cc.rengu.igas.acct.facade.base.Header header = new cc.rengu.igas.acct.facade.base.Header();
        header.setVersion("1.0.0");
        header.setTransDate(DateUtil.getCurrentDate());
        header.setTransTime(DateUtil.getCurrentTime());
        header.setTxnNum(dstTxnNum);
        header.setBizType("00");
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setChanlId(ChannelEnum.COPS.getChannelType());
        header.setInstId(instId);
        /*对账唯一key*/
        header.setTraceNo(virtAcctMultiMchntAdjustOrderInfo.getChannelReconKey());
        VirtAcctMultiMchntAdjustRequest request = new VirtAcctMultiMchntAdjustRequest();
        request.setHeader(header);
        /*统一账户类型*/
        request.setAcctType("00");
        /*统一记账类型*/
        request.setDebitCreditFlag("C");
        List<MchtAdjustDetail> mchtAdjustDetailList = new ArrayList<>();
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = null;
        String realPayAmt = null;
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            /*处理多笔记账明细*/
            MchtAdjustDetail mchtAdjustDetail = new MchtAdjustDetail();
            mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
            if ("11".equals(mchntInfo.getMchntType()) &&
                    !AppParamConstant.YES.equals(mchntInfo.getIndependentDataFlag())) {
                /*非独立清算商户，入连锁商户的虚拟账户*/
                mchtAdjustDetail.setUserId(mchntInfo.getChainMchntNo());
            } else {
                mchtAdjustDetail.setUserId(mchntInfo.getMchntNo());
            }
            /*判断是否是收支两线结算模式*/
            if ('1' == mchntInfo.getMchntSettleMode().charAt(1)) {
                realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getRealSettleAmt());
                mchtAdjustDetail.setTransAmt(mchntOrderInfo.getRealSettleAmt());
            } else {
                realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getMchntSettleAmt());
                mchtAdjustDetail.setTransAmt(mchntOrderInfo.getMchntSettleAmt());
            }
            /*用户类型*/
            mchtAdjustDetail.setUserType("00");
            /*如果商户记虚拟账户的金额等于0则不记该商户的虚拟账户*/
            if (AmountUtil.compare("0", mchtAdjustDetail.getTransAmt()) == 0) {
                continue;
            }

            mchtAdjustDetailList.add(mchtAdjustDetail);
        }

        /* 校验入账信息是否为空 */
        if (mchtAdjustDetailList.isEmpty()) {
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            //发送异步通知
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM, sysSeqNum);
            rglog.debug("需入账信息为空，开始异步调用消息推送交易......");
            /*记账成功后，调用微信消息推送*/
            int iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
            if (0 != iReturnCode) {
                rglog.error("提交交易结果异步通知给商户失败!");
            }
            return;
        }

        /*增加商户明细*/
        request.setMchtAdjustDetailList(mchtAdjustDetailList);
        /*登记实际记账总金额*/
        virtAcctMultiMchntAdjustOrderInfo.setRealPayAmt(realPayAmt);
        /*插入支付订单表*/
        if (!orderService.registerOrderInfo(null, null, virtAcctMultiMchntAdjustOrderInfo)) {
            rglog.error("登记单笔记账支付订单信息失败,instId:<{}>,sysSeqNum:<{}>,mchntOrderId:<{}>,msgDstId:<{}>",
                    virtAcctMultiMchntAdjustOrderInfo.getInstId(), virtAcctMultiMchntAdjustOrderInfo.getSysSeqNum(),
                    virtAcctMultiMchntAdjustOrderInfo.getMchntOrderId(), virtAcctMultiMchntAdjustOrderInfo.getMsgDstId());
            return;
        }
        rglog.debug("打印虚拟账户请求报文<{}>", JSON.toJSONString(request));
        /*异步调起虚拟账户记账*/
        int iReturnCode = dubboService.asynCallDubboService(ShareServiceConstant.VIRT_ACCT_SERVICE,
                ShareServiceConstant.VIRT_ACCT_MULTI_MCHNT_ADJUST_METHOD, request, ShareServiceConstant.VIRT_ACCT_SYNC_MULTI_MCHNT_ADJUST_SERVICE);
        if (iReturnCode != 0) {
            rglog.error("异步虚拟账户记账服务注册失败！");
        } else {
            rglog.info("异步虚拟账户记账服务注册成功！");
        }
    }

    @Override
    public void virtAcctMultiMchntAdjust(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {
        /*定义应用变量*/
        OrderService orderService = new OrderServiceImpl();
        DubboService dubboService = new DubboServiceImpl();
        /*初始化参数*/
        /*交易机构*/
        String instId = userOrderInfo.getInstId();
        /*原支付交易系统流水号*/
        String sysSeqNum = mchntOrderInfoList.get(0).getSysSeqNum();
        /*原支付交易交易码*/
        String txnNum = mchntOrderInfoList.get(0).getTxnNum();
        /*原支付交易业务细分*/
        String bizType = mchntOrderInfoList.get(0).getBizType();
        /*目标通道交易码*/
        String dstTxnNum = "P01AT002";
        /*初始化虚拟账记账订单*/
        PayOrderInfo virtAcctMultiMchntAdjustOrderInfo = new PayOrderInfo();
        virtAcctMultiMchntAdjustOrderInfo.setInstId(instId);
        virtAcctMultiMchntAdjustOrderInfo.setTxnDate(DateUtil.getCurrentDate());
        virtAcctMultiMchntAdjustOrderInfo.setTxnTime(DateUtil.getCurrentTime());
        /*虚拟账户单笔记账的交易码*/
        virtAcctMultiMchntAdjustOrderInfo.setTxnNum(txnNum);
        virtAcctMultiMchntAdjustOrderInfo.setBizType(bizType);
        /*通道交易码*/
        virtAcctMultiMchntAdjustOrderInfo.setDstTxnNum(dstTxnNum);
        /*系统流水号*/
        virtAcctMultiMchntAdjustOrderInfo.setSysSeqNum(sysSeqNum);
        /*单笔记账对账唯一主键,可以通过对账主键控制并发*/
        virtAcctMultiMchntAdjustOrderInfo.setChannelReconKey(sysSeqNum + "0");
        /*通道流水号*/
        virtAcctMultiMchntAdjustOrderInfo.setChannelSeqNum(sysSeqNum + "0");
        /*处理多笔商户订单交易*/
        if (mchntOrderInfoList.size() > 1) {
            /*多笔订单默认保存平台商户号*/
            virtAcctMultiMchntAdjustOrderInfo.setMchntNo(userOrderInfo.getGroupMchntNo());
        } else {
            /*单笔订单记录商户号*/
            virtAcctMultiMchntAdjustOrderInfo.setMchntNo(mchntOrderInfoList.get(0).getMchntNo());
        }
        /*商户订单号*/
        virtAcctMultiMchntAdjustOrderInfo.setMchntOrderId(userOrderInfo.getMchntOrderId());
        /*商户单笔记账金额*/
        virtAcctMultiMchntAdjustOrderInfo.setOrderAmt(userOrderInfo.getOrderAmt());
        virtAcctMultiMchntAdjustOrderInfo.setOrderCcy("156");
        /*设置通道标识和通道序号*/
        virtAcctMultiMchntAdjustOrderInfo.setMsgDstId(ChannelEnum.ACCT.getChannelType());
        /*设置支付类型*/
        virtAcctMultiMchntAdjustOrderInfo.setPayType("*");
        /*设置付款账户类型*/
        virtAcctMultiMchntAdjustOrderInfo.setPayerAcctType("*");
        /*设置通到序号*/
        virtAcctMultiMchntAdjustOrderInfo.setDstCallIndex("0");
        /*设置订单创建时间*/
        virtAcctMultiMchntAdjustOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        virtAcctMultiMchntAdjustOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        /*设置订单状态*/
        virtAcctMultiMchntAdjustOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        virtAcctMultiMchntAdjustOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        /*在异步程序中处理对应的订单状态*/
        /*组装请求报文头*/
        cc.rengu.igas.acct.facade.base.Header header = new cc.rengu.igas.acct.facade.base.Header();
        header.setVersion("1.0.0");
        header.setTransDate(DateUtil.getCurrentDate());
        header.setTransTime(DateUtil.getCurrentTime());
        header.setTxnNum(dstTxnNum);
        header.setBizType("00");
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setChanlId(ChannelEnum.COPS.getChannelType());
        header.setInstId(instId);
        /*对账唯一key*/
        header.setTraceNo(virtAcctMultiMchntAdjustOrderInfo.getChannelReconKey());
        VirtAcctMultiMchntAdjustRequest request = new VirtAcctMultiMchntAdjustRequest();
        request.setHeader(header);
        /*统一账户类型*/
        request.setAcctType("00");
        /*统一记账类型*/
        request.setDebitCreditFlag("C");
        List<MchtAdjustDetail> mchtAdjustDetailList = new ArrayList<>();
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = null;
        String realPayAmt = null;
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            /*处理多笔记账明细*/
            MchtAdjustDetail mchtAdjustDetail = new MchtAdjustDetail();
            mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
            if ("11".equals(mchntInfo.getMchntType()) &&
                    !AppParamConstant.YES.equals(mchntInfo.getIndependentDataFlag())) {
                /*非独立清算商户，入连锁商户的虚拟账户*/
                mchtAdjustDetail.setUserId(mchntInfo.getChainMchntNo());
            } else {
                mchtAdjustDetail.setUserId(mchntInfo.getMchntNo());
            }
            /*判断是否是收支两线结算模式*/
            if ('1' == mchntInfo.getMchntSettleMode().charAt(1)) {
                realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getRealSettleAmt());
                mchtAdjustDetail.setTransAmt(mchntOrderInfo.getRealSettleAmt());
            } else {
                realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getMchntSettleAmt());
                mchtAdjustDetail.setTransAmt(mchntOrderInfo.getMchntSettleAmt());
            }
            /*用户类型*/
            mchtAdjustDetail.setUserType("00");
            /*如果商户记虚拟账户的金额等于0则不记该商户的虚拟账户*/
            if (AmountUtil.compare("0", mchtAdjustDetail.getTransAmt()) == 0) {
                continue;
            }

            mchtAdjustDetailList.add(mchtAdjustDetail);
        }
        /*增加商户明细*/
        request.setMchtAdjustDetailList(mchtAdjustDetailList);
        /*登记实际记账总金额*/
        virtAcctMultiMchntAdjustOrderInfo.setRealPayAmt(realPayAmt);
        /*插入支付订单表*/
        if (!orderService.registerOrderInfo(null, null, virtAcctMultiMchntAdjustOrderInfo)) {
            rglog.error("登记单笔记账支付订单信息失败,instId:<{}>,sysSeqNum:<{}>,mchntOrderId:<{}>,msgDstId:<{}>",
                    virtAcctMultiMchntAdjustOrderInfo.getInstId(), virtAcctMultiMchntAdjustOrderInfo.getSysSeqNum(),
                    virtAcctMultiMchntAdjustOrderInfo.getMchntOrderId(), virtAcctMultiMchntAdjustOrderInfo.getMsgDstId());
            return;
        }
        rglog.debug("打印虚拟账户请求报文<{}>", JSON.toJSONString(request));
        /*异步调起虚拟账户记账*/
        int iReturnCode = dubboService.asynCallDubboService("virtAcctService", "virtAcctMultiMchntAdjust", request, "AsynVirtAcctMultiMchntAdjustService");
        if (iReturnCode != 0) {
            rglog.error("异步虚拟账户记账服务注册失败！");
        } else {
            rglog.info("异步虚拟账户记账服务注册成功！");
        }
    }


    @Override
    public void pushRiskMessage(String riskMessage, String alaramLevel, String respCode) {
        try {
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            TxnInfo txnInfo = (TxnInfo) xmlTreeUtil.getXmlTreeObjectValue(TreeNodeConstant.TXN_INFO,TxnInfo.class);
            DubboService dubboService = new DubboServiceImpl();
            AlarmNoticeRequest alarmNoticeRequest = new AlarmNoticeRequest();
            Header header = new Header();
            ConvertUtil.convertOutput(header);
            header.setTxnNum("0077000000RW01");
            header.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(header.getInstId()));
            alarmNoticeRequest.setHeader(header);
            alarmNoticeRequest.setAlarmLevel(alaramLevel);
            alarmNoticeRequest.setTransCode(txnInfo.getSrcTxnAuthCfg().getTxnNum());
            alarmNoticeRequest.setTransName(txnInfo.getSrcTxnAuthCfg().getTxnName());
            alarmNoticeRequest.setErrorCode(respCode);
            alarmNoticeRequest.setAlarmDesc(riskMessage);
            alarmNoticeRequest.setAlarmInfo(riskMessage);
            dubboService.asynCallDubboService(ShareServiceConstant.RISK_ALARM_SERVICE_NAME, ShareServiceConstant.ALARM_PLAT_SERVICE_METHOD, alarmNoticeRequest, ShareServiceConstant.ALARM_RESULT_PROC_SERVICE);
        } catch (Exception e) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            rglog.error("调用告警平台异常:<{}>", byteArrayOutputStream.toString());
        }
    }

    /**
     * 风险信息转换
     *
     * @param riskInfo 收银台上送的风险数据
     * @return 无卡快捷风险信息
     */
    private RiskInfo convertRiskInfo(RiskInfo riskInfo) {
        RiskInfo ncqsRiskInfo = new RiskInfo();
        ncqsRiskInfo.setDeviceMode(riskInfo.getDeviceMode());
        ncqsRiskInfo.setMac(riskInfo.getMac());
        ncqsRiskInfo.setDevId(riskInfo.getDevId());
        ncqsRiskInfo.setTermIp(riskInfo.getTermIp());
        return ncqsRiskInfo;
    }

    /**
     * 更新 订单为失败
     *
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @param payOrderInfo       支付订单
     * @param orderService       订单组件
     * @throws Exception 异常
     */
    private void updateOrderFail(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo, OrderService orderService) throws Exception {
        String currentDateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        /*更新订单表状态*/
        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
        userOrderInfo.setUpdateTime(currentDateTime);
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            mchntOrderInfo.setUpdateTime(currentDateTime);
        }

        if (null == payOrderInfo) {
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, null)) {
                rglog.error("更新订单表状态失败");
            }
        } else {
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            payOrderInfo.setUpdateTime(currentDateTime);
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                rglog.error("更新订单表状态失败");
            }
        }
    }


    /**
     * 快捷支付限额检查
     *
     * @param transAmt     支付金额
     * @param signAcctInfo 签约金额
     * @throws Exception 异常
     */
    void quickPayLimitCheck(String transAmt, SignAcctInfo signAcctInfo) throws Exception {
        List<TransLimitInfo> transLimitInfoList = new ArrayList<>();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        if (signAcctInfo.getSingleLimitAmt() != null && AmountUtil.compare(transAmt, signAcctInfo.getSingleLimitAmt()) == 1) {
            rglog.error("支付金额<{}>超过快捷支付单笔交易限额<{}>", transAmt, signAcctInfo.getSingleLimitAmt());
            throw new BizException(RespCodeEnum.OPM_OVER_AMT_LIMIT.getRespCode(), RespCodeEnum.OPM_OVER_AMT_LIMIT.getRespDesc());
        }
        /*快捷支付日累计限额*/
        if (signAcctInfo.getDayLimitAmt() != null && !signAcctInfo.getDayLimitAmt().isEmpty()) {
            TransLimitInfo transLimitInfo = new TransLimitInfo();
            transLimitInfo.setInstId(signAcctInfo.getInstId());
            transLimitInfo.setLimitType(LimitTypeEnum.PAY_ACCT.getLimitType());
            transLimitInfo.setLimitInst(signAcctInfo.getSignAcctNo());
            transLimitInfo.setSingleLimitMaxAmt(signAcctInfo.getSingleLimitAmt());
            transLimitInfo.setDayLimitAmt(signAcctInfo.getDayLimitAmt());
            transLimitInfo.setLimitAcctType(AcctTypeEnum.ALL.getAcctType());
            rglog.debug("限额限次实体:<{}>", JSON.toJSONString(transLimitInfo));
            transLimitInfoList.add(transLimitInfo);
        }
        if (!transLimitInfoList.isEmpty()) {
            String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
            String txnNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM);
            TransLimitService transLimitService = new TransLimitServiceImpl(instId, txnNum, null);
            if (!transLimitService.transLimitCheck(transAmt, transLimitInfoList)) {
                rglog.warn("限额检查不通过");
                throw new BizException(RespCodeEnum.OPM_OVER_AMT_LIMIT.getRespCode(), RespCodeEnum.OPM_OVER_AMT_LIMIT.getRespDesc());
            }

            TransLimitBean transLimitBean = new TransLimitBean();
            transLimitBean.setLimitInst(signAcctInfo.getSignAcctNo());
            transLimitBean.setOrderAmt(transAmt);
            transLimitBean.setTransLimitInfoList(transLimitInfoList);
            List<TransLimitBean> transLimitBeanList;
            if (xmlTreeUtil.isExist(ShareTreeNodeConstant.TRANS_LIMIT_INFO_LIST)) {
                transLimitBeanList = xmlTreeUtil.getXmlTreeListObjectValue(ShareTreeNodeConstant.TRANS_LIMIT_INFO_LIST, TransLimitInfo.class);
                transLimitBeanList.add(transLimitBean);
            } else {
                transLimitBeanList = new ArrayList<>();
                transLimitBeanList.add(transLimitBean);
            }
            xmlTreeUtil.setXmlTreeObjectValue(ShareTreeNodeConstant.TRANS_LIMIT_INFO_LIST, transLimitBeanList);
        }
    }

    /**
     * 转换营销的订单详情
     *
     * @param orderDetailList    营销订单详情
     * @param mchntOrderInfoList 商户订单表
     */
    void convertOrderDetail(List<PaymentOrderDetailBean> orderDetailList, List<MchntOrderInfo> mchntOrderInfoList, TxnInfo txnInfo, String acctType) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        String feeType;
        if (AcctTypeEnum.BANK_CREDIT.getAcctType().equals(acctType)) {
            feeType = FeeTypeEnum.BANK_CR_CARD.getFeeType();
        } else if (AcctTypeEnum.BANK_DEBIT.getAcctType().equals(acctType)) {
            feeType = FeeTypeEnum.BANK_DR_CARD.getFeeType();
        } else if (AcctTypeEnum.OTHER_DEBIT.getAcctType().equals(acctType)) {
            feeType = FeeTypeEnum.OTHER_BANK_DR_CARD.getFeeType();
        } else {
            feeType = FeeTypeEnum.OTHER_BANK_CR_CARD.getFeeType();
        }
        xmlTreeUtil.setXmlTreeStringValue("FEE_TYPE", feeType);

        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            PaymentOrderDetailBean paymentOrderDetailBean = new PaymentOrderDetailBean();
            paymentOrderDetailBean.setMchntNo(mchntOrderInfo.getMchntNo());
            if (mchntOrderInfo.getOrderDiscountAmt() != null && !mchntOrderInfo.getOrderDiscountAmt().isEmpty()) {
                paymentOrderDetailBean.setOrderAmt(AmountUtil.subtraction(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getOrderDiscountAmt()));
            } else {
                paymentOrderDetailBean.setOrderAmt(mchntOrderInfo.getOrderAmt());
            }
            paymentOrderDetailBean.setMchntFeeReceivableRate(mchntOrderInfo.getFeeRate());
            paymentOrderDetailBean.setMchntSettleAmt(mchntOrderInfo.getRealSettleAmt());
            paymentOrderDetailBean.setMchntFeeReceivable(mchntOrderInfo.getMchntFee());
            paymentOrderDetailBean.setFeeType(feeType);
            paymentOrderDetailBean.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
            orderDetailList.add(paymentOrderDetailBean);
        }
    }

    /**
     * 商户实时入账
     *
     * @param mchntOrderInfoList 商户订单
     * @param channelCallCfg     通道服务调用配置
     * @param roleActualAcctNo   角色账户信息
     */
    void mchntRealTimeAccouting(List<MchntOrderInfo> mchntOrderInfoList, ChannelCallCfg channelCallCfg, String roleActualAcctNo, String bizProdCode) throws Exception {
        //购买卡券的交易不支持实时入账
        if (isCouponTrans) {
            rglog.error("购买卡券交易，不实时入账");
            return;
        }

        DubboService dubboService = new DubboServiceImpl();
        int callIndex = Integer.parseInt(channelCallCfg.getCallIndex());
        int iReturnCode = 0;
        MchntService mchntService = new MchntServiceImpl();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            /*查询商户结算账户信息表，判断结算周期及结算账户类型*/
            MchntInfo mchntInfo;
            try {
                mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                List<MchntAcctInfo> mchntAcctInfoList;
                /*判断是否独立维护资料的门店*/
                if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                    mchntAcctInfoList = mchntService.getMchntAcctInfo(mchntOrderInfo.getInstId(), mchntInfo.getChainMchntNo());
                } else {
                    mchntAcctInfoList = mchntService.getMchntAcctInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                }
                Optional<MchntAcctInfo> mchntAcctInfoOpt = mchntAcctInfoList.stream().filter(item -> item.getBaseProdCode().equals(bizProdCode) && item.getFundType().equals("00")).findFirst();
                if (!mchntAcctInfoOpt.isPresent()) {
                    rglog.warn("获取商户结算账户信息失败，商户实时入账失败，转t1");
                }

                /*登记支付订单表*/
                PayOrderInfo payOrderInfo = registerD0PayOrderInfo(mchntOrderInfo, roleActualAcctNo, AcctTypeEnum.BANK_ACCT.getAcctType(),
                        mchntAcctInfoOpt.get().getSettleAcctNo(), mchntAcctInfoOpt.get().getSettleAcctType(), channelCallCfg, String.valueOf(callIndex));
                if (payOrderInfo == null) {
                    rglog.warn("渠道内部户不存在，转T1");
                    continue;
                }

                //发起记账
                //TODO 由项目组实现该部分 调用D0实时清算，后调用AsynMchntD0AccoutingService根据清算结果进行处理
                iReturnCode = dubboService.asynCallDubboService("dubboService", "method", "request", "AsynMchntD0AccoutingService");
                if (iReturnCode != 0) {
                    rglog.error("异步d0入账服务注册失败！");
                }
                callIndex++;
            } catch (Exception e) {
                rglog.error("商户实时入账异常:<{}>", e);
            }
        }
    }

    /*登记D0记账支付订单流水*/
    private PayOrderInfo registerD0PayOrderInfo(MchntOrderInfo mchntOrderInfo, String payAcctNo, String payAcctType, String payeeAcctNo, String payeeAcctType, ChannelCallCfg channelCallCfg, String callIndex) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();

        try {
            PayOrderInfo payOrderInfo = new PayOrderInfo();
            BeanUtil.beanCopy(mchntOrderInfo, payOrderInfo);
            payOrderInfo.setTxnNum(CopsParamConstant.D0_ACCOUTING_TXN_NUM);
            payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
            payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
            payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
            payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
            payOrderInfo.setPayerAcctType(payAcctType);
            payOrderInfo.setPayerAcctInfo(payAcctNo);
            payOrderInfo.setPayeeAcctType(payeeAcctType);
            payOrderInfo.setPayeeAcctInfo(payeeAcctNo);
            payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (callIndex != null) {
                payOrderInfo.setDstCallIndex(callIndex);
                payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + callIndex);
                payOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntOrderInfo.getInstId()));
            } else {
                payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
                payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
                payOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntOrderInfo.getInstId()));
            }
            if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
                rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
                return null;
            }
            return payOrderInfo;
        } catch (Exception e) {
            rglog.error("商户:<{}>实时记账异常:<{}>", mchntOrderInfo.getMchntNo(), e);
            return null;
        }
    }

    /**
     * 营销合并支付冲正
     */
    void mompRevsal(ChannelCallCfg mompRevsalChannelCallCfg) {
        DubboService dubboService = new DubboServiceImpl();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            if (xmlTreeUtil.isExist("discountFlag") && AppParamConstant.YES.equals(xmlTreeUtil.getXmlTreeStringValue("discountFlag"))) {
                String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);

                /*参与营销，异步调用营销冲正接口*/
                ComboPaymentRequest comboPaymentRequest = (ComboPaymentRequest) xmlTreeUtil.getXmlTreeObjectValue("comboPaymentRequest", ComboPaymentRequest.class);
                cc.rengu.igas.momp.facade.base.Header header = comboPaymentRequest.getHeader();
                header.setTxnNum(mompRevsalChannelCallCfg.getCallChannelTxn());
                header.setTraceNo(sysSeqNum + mompRevsalChannelCallCfg.getCallIndex());
                ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
                comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
                comboPaymentRevsalRequest.setHeader(header);
                int iReturnCode = dubboService.asynCallDubboService(ShareServiceConstant.MOMP_PAYMENT_SERVICE, ShareServiceConstant.MOMP_COMBO_PAYMENT_REVERSAL_METHOD, comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
                if (iReturnCode != 0) {
                    rglog.error("异步营销冲正服务注册失败！");
                }
            } else {
                return;
            }
        } catch (Exception e) {
            rglog.error("营销异步冲正服务调用异常:<{}>", e);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
    }

    /**
     * 购买卡劵的交易在交易成功后异步调起领取卡劵的服务
     *
     * @param mchntOrderInfoList 商户订单
     */
    void claimCoupon(List<MchntOrderInfo> mchntOrderInfoList) {
        if (!"00".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            return;
        }
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        DubboService dubboService = new DubboServiceImpl();
        String reserve = null;
        try {
            cc.rengu.igas.momp.facade.base.Header header = new cc.rengu.igas.momp.facade.base.Header();
            header.setChanlId(ChannelEnum.COPS.getChannelType());
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setBizType("00");
            header.setTxnNum("P01MO001");
            header.setVersion("1.0.0");
            header.setTraceNo(mchntOrderInfoList.get(0).getSysSeqNum() + "0");
            header.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
            header.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
            ClaimCouponRequest claimCouponRequest = new ClaimCouponRequest();
            claimCouponRequest.setHeader(header);
            List<ClaimCouponMcInfoBean> mcInfoList = new ArrayList<>();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                ClaimCouponMcInfoBean claimCouponMcInfoBean = new ClaimCouponMcInfoBean();
                claimCouponMcInfoBean.setPurchaseAmt(mchntOrderInfo.getOrderAmt());
                claimCouponMcInfoBean.setClaimQuantity("1");
                reserve = mchntOrderInfo.getTermNo();
                if (reserve != null) {
                    String[] mcInfo = reserve.split("\\|");
                    claimCouponMcInfoBean.setRuleIndex(mcInfo[1]);
                    claimCouponMcInfoBean.setMcNo(mcInfo[0]);
                }
                claimCouponMcInfoBean.setClaimUser(mchntOrderInfo.getUserId());
                claimCouponMcInfoBean.setClaimType("4");
                claimCouponMcInfoBean.setCouponLockFlag("1");
                mcInfoList.add(claimCouponMcInfoBean);
            }
            claimCouponRequest.setMcInfoList(mcInfoList);
            int iReturnCode = dubboService.asynCallDubboService("couponManagementService", "claimCoupon", claimCouponRequest, "AsynClaimCouponService");
            if (iReturnCode != 0) {
                rglog.error("异步卡券领取服务注册失败！");
            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
            rglog.error("异步卡券领取服务注册失败！");
        }

    }


    protected boolean updateOrderInfo(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo) throws Exception {
        int iReturnCode;
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppParamConstant.DATABASE_CONF_NODE, AppParamConstant.OLTP_POOL_NAME);
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String bizStatus = userOrderInfo.getBizStatus();
        rglog.debug("更新用户订单/商户订单/支付订单，当前用户订单业务状态:<{}>", bizStatus);
        userOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        userOrderInfo.setTxnNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM));
        userOrderInfo.setUserId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.USER_ID));
        /* Step1：开启数据库事务 */
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppParamConstant.OLTP_POOL_NAME);
            dbsUtil = new DbsUtil(dbPoolName);
        }
        dbsUtil.dbsBeginTransaction();
        /* Step2：更新用户订单信息 */
        if (null != userOrderInfo) {
            UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
            iReturnCode = userOrderInfoMapper.updateUserOrderInfoByUserOrderId(userOrderInfo);
            if (0 != iReturnCode) {
                dbsUtil.dbsEndTransaction(false);
                return false;
            }
        }
        /* Step3：更新商户订单信息 */
        if (null != mchntOrderInfoList && !mchntOrderInfoList.isEmpty()) {
            MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                //mchntOrderInfo.setUserId(xmlTreeUtil.getXmlTreeStringValue(OpmTreeNodeConstant.USER_ID));
                if (BizStatusEnum.INIT.getStatus().equals(bizStatus) || bizStatus == null) {
                    rglog.debug("当前订单为初始订单，直接更新对应商户订单");
                    /*新建订单时更新商户订单*/
                    iReturnCode = mchntOrderInfoMapper.updateMchntOrderInfoByMchntOrderId(mchntOrderInfo);
                    if (0 != iReturnCode) {
                        dbsUtil.dbsEndTransaction(false);
                        return false;
                    }
                } else {
                    rglog.debug("当前订单不是初始订单，需要插入新的商户订单");
                    /*失败后支付的插入新的订单*/
                    mchntOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
                    mchntOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
                    iReturnCode = mchntOrderInfoMapper.insertMchntOrderInfo(mchntOrderInfo);
                    if (0 != iReturnCode) {
                        dbsUtil.dbsEndTransaction(false);
                        return false;
                    }
                }
            }
        }
        /* Step4：更新支付订单信息 */
        if (null != payOrderInfo) {
            PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
            iReturnCode = payOrderInfoMapper.updatePayOrderInfoByPrimaryKey(payOrderInfo);
            if (0 != iReturnCode) {
                dbsUtil.dbsEndTransaction(false);
                rglog.error("更新支付订单信息失败,sysSeqNum:<{}>,mchntOrderId:<{}>,channelId:<{}>,realPayAmt:<{}>,channelFee:<{}>,settleDate:<{}>,channelSeqNum:<{}>,iReturnCode:<{}>",
                        payOrderInfo.getSysSeqNum(), payOrderInfo.getMchntOrderId(), payOrderInfo.getMsgDstId(), payOrderInfo.getRealPayAmt(), payOrderInfo.getChannelFee(), payOrderInfo.getSettleDate(), payOrderInfo.getChannelSeqNum(), iReturnCode);
                return false;
            }
        }
        /* Step5：结束数据库事务 */
        dbsUtil.dbsEndTransaction(true);
        return true;
    }
}
